﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using BomberManServer.Gaming;
using BomberManServer.Gaming.Object;
using BomberManServer.Threading;
using BomberManServer.UI;
using BomberManServer.Utils;
using WebService = BomberManServer.WebService;

namespace BomberManServer
{
    public partial class Form1 : Form
    {
        Logger logger;
        Logger.Handler handler;
        Logger.Thread thread;
        ThreadedSocketPool pool;
        LinkedList<Game> games;
        bool quit;
        WebService.ProxyService proxy;

        public Form1()
        {
            InitializeComponent();

            quit = false;
            FormClosed += new FormClosedEventHandler(onFormClosed);

            // create Logger
            logger = new Logger();

            // bind Logger
            thread = logger.createThread();
            thread.Message += textLog.AppendText;

            // create a Handler
            handler = thread.createHandler("Main");

            // create the pool
            pool = new ThreadedSocketPool(Constants.instance.baseSocket, Constants.instance.maxThreadPool);

            games = new LinkedList<Game>();
            
            proxy = new WebService.ProxyService();
            proxy.start();
            
        }

        private void buttonStop_Click(object sender, EventArgs e)
        {
            handler.information("Stopping Server\n");
        }

        private void buttonStart_Click(object sender, EventArgs e)
        {
            // Create the match
            Player player1 = new Player(152, 15, "Guillou", 0, 0, 0, 0);
            Player player2 = new Player(153, 32, "Quentou", 0, 0, 0, 0);
            Player player3 = new Player(154, 17, "Cricrou", 0, 0, 0, 0);
            Player player4 = new Player(155, 20, "Benou", 0, 0, 0, 0);

            Team team1 = new Team(0);
            Team team2 = new Team(1);
            Team team3 = new Team(2);
            Team team4 = new Team(3);
            team1.add(player1);
            team2.add(player2);
            team3.add(player3);
            team4.add(player4);
            Match match = new Match(1, Match.MatchType.SOLO);
            //Match match = new Match(1, Match.MatchType.FFA);
            match.add(team1);
            match.add(team2);
            //match.add(team3);
            //match.add(team4);

            createGame(match);
        }

        private int createGame(Match match)
        {
            if (pool.isBusy())
            {
                handler.information("Too many Threads !\n");
                return 0;
            }

            handler.information("Grabing thread in the pool\n");
            ThreadedSocket thread = pool.grab();
            int port = ((IPEndPoint)thread.socket.LocalEndpoint).Port;
            handler.information("Thread listening on port " + port + "\n");
           
            // Setup a game
            Game game = new Game(thread, match, logger.createThread());
            games.AddLast(game);

            // TODO clean this stuff and handle UI better
            // Some UI stuff
            System.Windows.Forms.TabPage tabPage1;
            ThreadControl threadControl1;

            tabPage1 = new System.Windows.Forms.TabPage();
            threadControl1 = new UI.ThreadControl();
            tabPage1.SuspendLayout();
            // 
            // tabPage1
            // 
            tabPage1.Controls.Add(threadControl1);
            tabPage1.Location = new System.Drawing.Point(4, 22);
            tabPage1.Padding = new System.Windows.Forms.Padding(3);
            tabPage1.Size = new System.Drawing.Size(433, 207);
            tabPage1.Text = "Thread " + port;
            tabPage1.UseVisualStyleBackColor = true;
            // 
            // threadControl1
            // 
            threadControl1.Location = new System.Drawing.Point(57, 38);
            tabPage1.ResumeLayout(false);
            tabControl1.Controls.Add(tabPage1);

            // TODO Not thread safe
            // attach the textarea to the Logger
            game.logger.Message += threadControl1.textBox.AppendText;

            // start the game
            thread.start(game.start);
            return port;
        }

        // the main loop
        public bool loop()
        {
            Match match = null;
            // check if a game has ended
            LinkedListNode<Game> next;
            for( LinkedListNode<Game> node = games.First; node != null; node = next) {
                Game game = node.Value;
                next = node.Next;
                // send stats to the WS
                if (game.finished)
                {
                    if (proxy.connected)
                        proxy.onGameFinished(game.stats);
                    games.Remove(node);
                }
            }

            if (proxy.connected)
            {
                // check messages from the WS
                if (proxy.checkMatchRequest(out match))
                {
                    int port = createGame(match);
                    proxy.onGameStarted(port, match);
                }
            }
            
            // dispatch logs
            logger.dispatch();
            return !quit;
        }

        public void onFormClosed(object sender, FormClosedEventArgs e)
        {
            quit = true;
        }
    }
}
